#ifndef __NEWMUSICENGINE_H__
#define __NEWMUSICENGINE_H__

#include "NetworkEngine/NetworkMusicFile.h"
#include "NetworkEngine/NetworkLyricFile.h"
struct AVFormatContext;
namespace SPlayer
{
    namespace Music
    {
        using namespace Network;
        ref class MusicEngine;
        class MusicEngineInternalVarables;

        ref class NewMusicEventDispatcher
        {
        public:
            System::Action ^onPlayed;
            System::Action ^onStoped;
            System::Action ^onPaused;
            System::Action ^onContinued;
            System::Action ^onFinished;
        };
        enum class MusicEngineState
        {
            Stoped,
            Playing,
            Paused
        };
        ref class MusicEngine
        {
        private:
            MusicEngine();
            ~MusicEngine();
            !MusicEngine();
        public:
            static bool init();

            // methods:
        public:
            void stop();
            bool pause();
            bool continuePlay();

            /*! @brief Play with a custom io stream(assume not seekable).
             *! @param iostream the custom io stream, which must provide \
             *! at least Read method.
             *! @param duration if you know the real duration of playing music, \
             *! set it. Otherwise, reserve it as 0. You can use FFmepg to retrive \
             *! the duration of the music at somewhere else(eg, server side), \
             *! then send it to this function.*/
            bool playWithCustomIOStream(IO::Stream ^iostream, long long duration);

            /* @brief Play with a file*/
            bool playWithFile(System::String ^filename);
            
        private:
            bool play(AVFormatContext *ic_provided);
            // music properties:
        public:
            property MusicEngineState state
            {
                MusicEngineState get();
            }
            /*! @check whether there is music playing, including pausing.
             *! @note this attribute is deprecated, use \c state instead.*/
            __declspec(deprecated) property bool hasMusic { bool get(); }
            /*! @brief playing music's length, in milliseconds. */
            property unsigned length { unsigned get(); }
            property unsigned playOffset { unsigned get(); void set(unsigned offset); }
            /*! @brief volume between 0(mute) and 1(full volumn). */
            property double volume{ double get(); void set(double volume); }

            // variables:
        public:
            NewMusicEventDispatcher ^eventDispatcher = gcnew NewMusicEventDispatcher;

            // internal variables:
        private:
            MusicEngineInternalVarables *vars = nullptr;

            // static public variables:
        public:
            static MusicEngine ^currentEngine = nullptr;
        };
        //-----------------------------------------------------------
    }
}
#endif // __NEWMUSICENGINE_H__